﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2011-08-04
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class IFWorkTimer;
class IFAnimTimer;
class IFDataTimer;


//----------------------------------------------------------------
// 整个系统的工作时间情况，Fuel4D 引擎的当前运行时间即用此对象
//----------------------------------------------------------------
class IFWorkTimer : public IFMemObject
{
protected:
    explicit IFWorkTimer()
    {}

public:
    // 重置
    virtual void Reset() = 0;
    // 开始
    virtual void Start() = 0;
    // 停止
    virtual void Stop() = 0;
    // 步进
    virtual void Advance() = 0;
    // 取绝对时间（从系统开机到现在）
    virtual double GetAbsoluteTime() = 0;
    // 取当前时间（从调用开始到现在）
    virtual double GetTime() = 0;
    // 获取当前秒的流逝时间
    virtual float GetElapsedTime() = 0;
    // 整体获取
    virtual void GetTimeValues(double* pfTime, double* pfAbsoluteTime, float* pfElapsedTime) = 0;
    // 是否停止中
    virtual bool IsStopped() = 0;
    // 将计时器与特定的CPU绑定，以单CPU计算出更精准的时间
    virtual void LimitThreadCpu() = 0;
};


//----------------------------------------------------------------
// 带区间时间的动画时间控制器
//----------------------------------------------------------------
class IFAnimTimer : public IFMemObject
{
protected:
    explicit IFAnimTimer()
    {}

public:
    // 开始播放
    virtual void Play(EF_ANIMATE_MODE mode, DWORD start_time, DWORD start_frame_id, DWORD end_frame_id, DWORD one_loop_time = 0, int freq = F_DEFAULT_FREQ) = 0;
    // 获取指定时间的帧ID，ntime必须于开始时间
    virtual DWORD GetFrameID(DWORD ntime) = 0;
    // 获取指定时间的帧ID，ntime必须于开始时间
    // .t 返回该帧的此区间的百分比
    virtual DWORD GetFrameID(DWORD ntime, float& t) = 0;
    // 取整体播放进度
    virtual float GetTotalPercent(DWORD ntime) = 0;
    // 取当前的播放流水线进度（不是区间进度，因区间是支持反向的）
    virtual float GetLoopPercent(DWORD ntime) = 0;
    // 取当前已经循环了多少次数
    virtual DWORD GetNumLooped(DWORD ntime) = 0;
    // 获取循环完当前区间所需要的时间
    virtual DWORD GetOneLoopTime() = 0;
    // 获取开始时间
    virtual DWORD GetStartTime() = 0;
    // 设置循环当前区间所需时间
    virtual void SetOneLoopTime(DWORD lt) = 0;
    // 获取开始帧ID
    virtual DWORD GetStartFrameID() = 0;
    // 获取结束帧ID
    virtual DWORD GetEndFrameID() = 0;
    // 设置循环模式
    virtual void SetMode(EF_ANIMATE_MODE mode) = 0;
    // 获取当前循环模式
    virtual EF_ANIMATE_MODE GetMode() = 0;
    // 重置时间
    virtual void Reset() = 0;
    // 设置单帧模式，并设置帧ID
    virtual void SetSingle(DWORD id) = 0;
    // 测试是否是单帧模式
    virtual bool IsSingle(){ return GetMode() == eAM_Single; }
};


//----------------------------------------------------------------
// 当前时间获取器
//----------------------------------------------------------------
class IFDataTimer : public IFMemObject
{
protected:
    explicit IFDataTimer()
    {}

public:
    #pragma pack(push, 1)
    struct NET_DATA
    {
        // 年月日时分秒-本初子五时间
        WORD wYear;
        BYTE wMonth, wDay, wHour, wMinute, wSecond;

        NET_DATA(){ FMemzero(this, sizeof(*this)); }
    };
    #pragma pack(pop)

    // 生成当前时间
    virtual void MakeTime() = 0;
    // 添加一段时间
    virtual void AddTime(int nDay, int nHour, int nMinute, int nSecond) = 0;
    // 时间数据是否有效
    virtual bool IsValid() = 0;
    // 清空时间日期
    virtual void Zero() = 0;
    // 大于
    virtual bool Greater(IFDataTimer* right) = 0;
    // 等于
    virtual bool Equal(IFDataTimer* right) = 0;
    // 转换到网络结构
    virtual void GetToNetData(NET_DATA* ptimer) = 0;
    // 通过网络结构设置数据
    virtual void SetFromNetData(NET_DATA* ptimer) = 0;
    // 拼接时间日期字符串（年月日时分）
    FINLINE const NCHAR* MakeString (NCHAR* buffer, size_t len, const NCHAR* head, const NCHAR* tail);
#if !(FUEL_OS_ANDROID)
    virtual const WCHAR* MakeStringW(WCHAR* buffer, size_t len, const WCHAR* head, const WCHAR* tail) = 0;
#endif
    virtual const ACHAR* MakeStringA(ACHAR* buffer, size_t len, const ACHAR* head, const ACHAR* tail) = 0;
    // 拼接时间完整日期字符串（年月日时分秒）
    FINLINE const NCHAR* MakeString (FString & out, const NCHAR* head, const NCHAR* tail);
#if !(FUEL_OS_ANDROID)
    virtual const WCHAR* MakeStringW(FStringW& out, const WCHAR* head, const WCHAR* tail) = 0;
#endif
    virtual const ACHAR* MakeStringA(FStringA& out, const ACHAR* head, const ACHAR* tail) = 0;
};

FINLINE const NCHAR* IFDataTimer::MakeString (NCHAR* buffer, size_t len, const NCHAR* head, const NCHAR* tail)
{
#ifdef UNICODE
    return MakeStringW(buffer, len, head, tail);
#else
    return MakeStringA(buffer, len, head, tail);
#endif
}

FINLINE const NCHAR* IFDataTimer::MakeString (FString & out, const NCHAR* head, const NCHAR* tail)
{
#ifdef UNICODE
    return MakeStringW(out, head, tail);
#else
    return MakeStringA(out, head, tail);
#endif
}

extern FAPI IFWorkTimer* FNewWorkTimer(FNEW_FUNC_API);
extern FAPI IFAnimTimer* FNewAnimTimer(FNEW_FUNC_API);
extern FAPI IFDataTimer* FNewDataTimer(FNEW_FUNC_API);
